\chapter{相关工作}

本章将分别介绍云环境中数据存储、深度学习计算、以及安全可信等几方面的相关工作。

\section{数据存储}
云环境下的数据存储问题是近年来云计算研究的重点，一方面有针对云存储中每个单机节点内部存储架构进行优化的研究工作，以高性价比的原则提升
单机存储的效率、可用性等；另一方面，由于云存储中的数据量远超单机存储的容量，有许多针对分布式存储架构的研究，来将大规模数据存储到多个服务器中，

\subsection{分布式存储}
在大数据时代，海量的数据规模已远超单机存储的容量极限、因此，采用分布式存储来扩展单机存储容量的做法势在必行，并直接催生出了云存储技术。
分布式存储是云存储技术的基础，而云存储是分布式存储的上层扩展。
云存储通过虚拟化技术\cite{xen,kvm,vmware}将物理存储资源抽象为逻辑存储资源，并向用户提供逻辑存储接口，
逻辑存储可以是一个文件或存储对象提供给用户使用，
如微软的OneDrive\cite{OneDrive}、百度云盘\cite{baiduyun}等。
在云存储中，用户只需要关心其可以使用的存储空间的规模大小，但并不需要知道其所使用的存储的真实物理位置和物理地址，
逻辑地址到物理地址的转换则由下层的分布式存储技术完成，如HDFS\cite{hdfs}，Ceph\cite{ceph}。

分布式存储需要重点考虑系统的可靠性与可用性问题，
数据可靠性是指数据不会因故障（例如断电或硬件损坏）丢失且无法恢复，可用性是指数据始终可以保持低延迟的正常访问。
在分布式存储系统中，虽然每个个体服务器宕机的几率较小，但总体存在故障发生的概率会随着节点数增多不断放大，
对于规模庞大的云服务器集群而言，有服务器宕机无法访问是一种常态。当有节点出现故障而无法访问时，
首先必须保证该节点上的数据不会因为故障而丢失，其次希望能通过其他正常服务器继续提供访问。
一种常用的解决方法是冗余副本技术RAID\cite{raid,raid5}，其对每个数据块都存储了多份副本在不同节点上，
这样只要不是所有副本服务器全部宕机了，数据仍然可以从其他服务器那里访问，保证了系统的可用性。
并且，除非所有副本服务器全部损坏，数据可以从其他副本节点重新恢复，保证了系统的可靠性。

分布式存储使用块存储来提供存储负载均衡，如：OpenStack Swift\cite{swift}的虚拟主机和Ceph的PG\cite{ceph}。
虚拟主机是物理主机到逻辑层面的映射，虚拟主机数量通常会大于实际物理主机的数量，一个物理机可对应了多个虚拟主机，
并且存储容量大的物理机会映射到更多的虚拟主机。当需要数据发生迁移时，例如从集群中删除某个物理主机，
会将该物理主机的存储重新映射到多个虚拟主机上，由于虚拟主机同时对应了多个不同的物理主机，从而避免了点对点高带宽传输，
并使得新数据分布更加均匀。

\subsection{HDD-SSD协同存储架构}
分布式存储集群的下层是实际物理存储节点，物理存储节点的存储架构也需适应分布式存储及更高级别的云存储的需求。
云存储平台具有低成本的需求，而HDD-SSD协同存储结构可以提供这一点。

DM-cache\cite{url_dmcache}和其变种（Bcache\cite{url_bcache}、Flashcache \cite{url_flashcache}）是Linux内核模块，
用于将快速SSD与慢速HDD作为虚拟块设备相结合，其中快速SSD作为慢速HDD的缓存，当缓存命中时，I/O可绕过HDD在SSD上执行以提高I/O效率。
DM-cache及其变种既具备HDD的低成本优势，又能提供了SSD接近的高I/O速度，
被广泛用于云存储底层的物理节点存储设计上。
DM-cache与其变种不同的是，Bcache使用btree作为缓存结构，而Flashcache缓存结构为关联哈希表。
此外，另一种内核模块LVMcache\cite{url_lvmcache}基于DM-cache顶部，使用逻辑卷以避免计算块偏移和大小。

DM-cache的主要问题在于：其发生崩溃后的恢复时间十分缓慢，为了保持HDD与SSD上的数据一致性，
恢复时必须默认所有的SSD缓存块都是脏的。
日志机制（Journal）被广泛用于保持存储系统崩溃后的数据恢复一致性，
但基于日志\cite{258965}的元数据写对于DM-cache来说是低效的\cite{DBLP:journals/chinaf/WangXLWC19}。
为了保持一致性，基于日志的解决方案总是对写顺序施加限制（例如，数据->同步->元数据->同步）\cite{chidambaram2013optimistic}，
这既增加了延迟，又减少了I/O吞吐量。

此外基于硬件的带外解决方案\cite{202260}需要具有高度复杂编程的特殊硬件和驱动程序支持，
最近出现的开放式通道SSD\cite{url_oc}较难购得，据我们所知，拥有数百万SSD的大型云提供商往往只有几千个具有开放通道自定义支持的SSD。
此外，NVM\cite{url_nvm} 基于\cite{258860, DBLP:journals/tc/ChenLCS19, DBLP:journals/tos/ChengLZQLB21, 
DBLP:conf/hpcc/VenkatesanWT14, DBLP:journals/access/ZhuLWZZM17}的解决方案虽然是有希望的，但目前造价十分昂贵，与DM-cache低成本的目的相违背。

除了Linux内核提供的SSD缓存机制外，一些SSD-HDD混合设计还使用SSD作为主存储设备，
例如，Nitro~\cite{li2014nitro}设计了一个容量优化的SSD用于主存储。
固态混合驱动器（SSHD~\cite{djordjevicsshd}）将SDD集成到传统的HDD硬件上，实现了一种新型磁盘硬件，并以类似于Nitro的方式实现SSD缓存。
URSA\cite{li2019ursa}是一个分布式块存储系统，它将主要副本存在于SSD上，并在HDD上复制备份副本。
Griffin~\cite{soundararajan2010extending}设计了一个混合存储设备，它使用HDD作为SSD的写缓存，以延长SSD的使用寿命。

\subsection{日志结构存储}

DM-cache在硬件层面上实现了云存储物理节点配备的低成本，而在软件层面上，日志结构存储LSM（Log Structured Merge Tree）
在云存储中具有十分可期的发展前景，并被广泛研究。LSM架构利用顺序写速度大于随机写速度的磁盘特性，将随机写转化为顺序追加写的方式来大幅提高写速度，
被广泛用于写频繁的大型分布式数据库的存储引擎，如：LevelDB\cite{leveldb} , 
RocksDB\cite{rocksdb} ，HBase\cite{hbase}, Cassandra\cite{cassandra}, MongoDB\cite{mongodb}。
LSM并不对kv进行本地更新（物理位置保持不变的更新方式），而是将每个kv写请求以追加写的方式补充到磁盘的末尾，这样所有的随机写请求都会转化为顺序写从而提高写速度。
LSM首先在内存中维护一个以key为序的kv序列（Memtable），当产生一个读请求时（根据key查找value），LSM会先在内存中对该key进行查找，
若找到，则返回该key的value。对于kv写请求，LSM总是先将其加入Memtable，此时并不会直接触发写IO。
由于内存的容量远小于存储的总量，因此当内存中的Memtable的大小达到临界值时，会将其以追加写的方式持久化至磁盘，并变成一个SSTable。
因此，如果读请求未在内存中命中，则会再前往磁盘查找该key。LSM在磁盘上维护了多个SSTable（Sorted String Table），因此可能存在多个相同key的kv，
显然，后写入的SSTable会持有更新的kv版本，因此读请求查找磁盘的过程为从后往前依次进行查找，查找到的第一个key则立即返回其value。
由于每个SSTable都是一个有序的kv序列，查找过程可以使用二分查找，复杂度为$O(logN)$。

从后往前遍历每个SSTable的过程中可能会经过大量不必要的SSTable，最好情况下，在最靠后的SSTable就直接找到了该kv，
但最坏情况也可能会遍历到最靠前的SSTable，或者该kv根本不在存储中，那么必然会遍历完所有的SSTable。为此，LSM存储常使用
布隆过滤器\cite{bloom}来排除掉一部分无用的SSTable查找。布隆过滤器可快速判断一个元素是否属于某个集合。
布隆过滤器有可能产生误报（false positive），即将元素不存在于集合返回为存在，但一定不会产生漏报（false negative，将存在返回为不存在），
对于SSTable的查找而言，只要不产生漏报，误报是可以容忍的。

LSM通过追加写的方式降低了整体的随机写开销，但缺点是会容易产生空间写放大：随着写入的SSTable不断变多，重复的kv也会越来越多，
而由于只有磁盘上最靠后的key持有最新value，之前重复的kv实际上都已经失效，因此磁盘的实际存储空间要小于被用掉的空间。
显然，空间写放大会随着时间累积越来越明显，最终会导致存储空间完全丧失。
为了解决这个问题，LSM引入了合并机制（Compaction）来回收之前失效的kv，并将其重新设为可用空间，此过程也称为垃圾回收。
垃圾回收很大程度上影响了LSM存储的整体性能，为此，PebblesDB\cite{pebblesdb}提出了基于跳表思想的FLSM结构，
可以大幅减少compaction中的写放大问题。

LSM存储也被广泛用于文件系统设计中，如F2FS\cite{f2fs}，Sprite LFS\cite{spritefs}。
LSM文件系统也使用追加写的方式写数据块，并且在元数据中保存逻辑块地址LBA(Logical Block Address)到物理块地址(Physical Block Address)的映射。
当要查找某个LBA对应的数据块时，会先进入元数据区找到LBA-PBA的映射，再根据PBA找到数据块。
因此可以认为LSM文件系统实际也存储了key-value对集合，而这些key-value特指LBA-PBA的映射。
LSM文件系统区别于数据库LSM存储引擎的地方在于：文件系统访问的最终对象是文件，文件又由一系列数据块组成；
而数据库的最终对象是key-value。所以对于LSM文件系统而言，在元数据区查找完LBA-PBA之后，
还要额外进行一个根据PBA访问数据块的动作；而对于数据库而言，当找到key-value后将会直接返回。
所以，在LSM文件系统中，实际存在有种类型的追加写，一是数据块的追加写，二是由kv（LBA-PBA）组成的SSTable的追加写，
而数据库LSM存储引擎中只有kv的追加写。

\section{深度学习}
近年来，以深度学习DL（Deep Learning）为代表的智能计算已经成为一种新兴的大数据分析方式，并被广泛部署于云端，
许多云平台都提供基于深度学习的SaaS级商业应用\cite{saasapp}。
深度学习在许多领域，例如图像识别、自然语言处理、推荐系统都发挥了重要作用。
由于应用面广泛，深度学习是近年来计算机领域最热门的研究方向之一，
研究的内容主要包括有：深度学习框架、面向深度学习的处理器优化、深度学习算法SGD、弹性训练等。

\subsection{深度学习框架}
深度学习框架的内涵实际十分广泛，狭义上通常指深度学习平台，广义上还包含深度学习通信框架、部署方案等等。
深度学习平台如Tensorflow\cite{tf}、MXNet\cite{mxnet}、Caffe\cite{caffe}、Pytorch\cite{pytorch}
可以理解为是一种帮助程序员实现深度学习任务的工具，它使程序员可以在无需深入了解底层算法的细节的情况下，
更容易、更快速地构建深度学习模型。深度学习平台利用预先构建和优化好的组件集合定义模型，为模型的实现提供了一种清晰而简洁的方法，
以用于支持CPU、GPU进行DNN模型等机器学习算法的运算，如今也广泛支持DNN模型的并行计算。

随着深度学习在诸多等商业场景的落地以及学术界深度模型设计研究的推进，
深度模型设计越来越复杂\cite{cnn2,cnn3}，任务计算量和所学资源规模也随之增长，单机训练方法开始难以满足复杂模型的训练，
因此计算力更强的并行训练方法\cite{large1,large2}得到广泛研究，并被大规模部署到云端。

相应的，针对分布式深度学习的软件架构开发也被广泛研究，并在不断的快速迭代中更新成长。
参数服务器PS（Parameter Server）\cite{ps}最初被设计用于并行机器学习算法的参数同步，如今已作为基本的分布式深度学习通信框架
被内置于Tensorflow、MXNet、Pytorch中。
更先进的Horovod\cite{DBLP:journals/corr/abs-1802-05799}使用Ring-All-Reduce通信模型，在Ring-All-Reduce中，所有通信节点构成一个环形结构，
并且只从自己左手侧的节点接收参数，通过两次逆时针参数传递以完成参数同步。
Spark\cite{spark}最初被设计用于大规模分布式机器学习框架，实际也具备执行深度学习任务的能力，
并常常与深度学习平台相结合，得益于其在分布式存储（文件系统、数据库）上的强有利支撑，
仍然可在激烈的竞争中占据一席之地，如：Amazon Retail System使用Spark执行了1000亿存储量级的推荐系统任务\cite{ars}。
并且Spark目前可以支持基于Java语言的深度学习程序设计\cite{djl}，这使得用户可以对更底层的深度学习算子进行改装和再开发，
而主流深度学习平台在算子上主要依赖于高性能数学库\cite{mkldnn,cudnn}。
随着容器化技术\cite{docker}的在深度学习领域的进一步实践，改善并解决了相当一部分深度学习部署困难的问题，也降低了深度学习的门槛。
NVIDIA以开发插件的方式支持Kubernetes\cite{k8s}调度GPU容器。

\subsection{随机梯度下降算法}
DNN模型的数据并行训练广泛采用随机梯度下降算法或stochastic gradient descent（SGD），
最先进的深度学习方法通常使用同步 SGD~\cite{sync1,sync2,large1,lars}进行训练，因为经验上，
基于同步SGD的分布式训练比异步 SGD~\cite{staleness,variance,asynchronous,async0}准确性更高和收敛速度更快。
模型并行\cite{modelp,modelp2}的方案由于DNN网络层相关性依赖十分复杂的原因设计较为困难，研究相对较少。
因此，本文将重点关注数据并行同步SGD。

\noindent
\textbf{迷你批次SGD.}
给定以权重$w$参数化的神经网络，以及随机抽样的输入数据$X$, 损失函数$L(\dot)$以以下方式计算，其中函数$l(\dot)$是单个输入数据的损失函数:

\vspace{-4mm}
%\begin{equation}
\begin{align*}
	\label{e3}
	L(w, X) = \frac{1}{|X|}\sum_{x \in X}l(w,x)
	\tag*{(1)}
\end{align*}

在每次迭代中,权重$w$以以下方式进行更新, 其中$\eta$是学习率:

\vspace{-4mm}
%\begin{equation}
\begin{align*}
	\label{e3123}
	w_{t+1} = w_{t} - \eta L(w_{t}, X)
	\tag*{(2)}
\end{align*}

实际过程中,使用动量SGD~\cite{momenmtum}可以更好地加速收敛. 动量状态保留过去梯度的加权值，并使用以下规则对权重进行更新：

\vspace{-4mm}
%%\begin{equation}
\begin{align*}
	\label{e3456}
	\begin{array}{lr}
		u_{t+1} = mu_{t} - L(w, X) \\
		w_{t+1} = w_{t} - \eta u_{t+1}
	\end{array}
	\tag*{(3)}
\end{align*}

\noindent
\textbf{参数服务器.}
参数服务器（PS）~\cite{ps}是分布式迷你批次SGD（Mini-batch SGD）的通信框架。PS中有两个角色：worker和server。
在每次迭代的同步中，每个Worker将梯度推至服务器，然后Server根据梯度更新权重，再将权重返回给每个Worker。同步 SGD的迭代可描述为四个步骤：

\begin{itemize}
	\item 第一步，每个worker计算其本地梯度$g_i$=$w$；
	\item 第二步，每个worker将其本地梯度$g_i$推至服务器；
	\item 第三步, server将所有$g_i$累加到全局梯度$G=\sum g_i$上；
	\item 第四步, server通过全局梯度$G$更新权重$w=w+\eta\cdot G$；
	\item 第五步, 每个worker将权重$w$从server上拉到本地。
\end{itemize}

\noindent
\textbf{线性学习率增长原则.}
经验上，多机并行的学习率设定依照线性缩放原则\cite{large1}：学习率与批次总大小按同样方式缩放，例如，如果批次大小乘以 $k$，学习率也应乘以 $k$。
根据一般的多机并行设置，我们在并行中线性增加worker数量，使得总批次大小等于worker数乘每个worker的批次大小，这样按照线性学习率增长原则，
总的学习率也是worker个数乘上每个worker的学习率，每个worker的学习率应与单节点模式保持不变。

由于异步SGD的通信量较低，因此其收敛速度比同步 SGD~\cite{asy1,asy2}更快，然而与同步 SGD 相比，在同一训练时间内异步SGD很难获得与同步 SGD相同的精度~\cite{large_scale,revisiting}。
Facebook~\cite{large1}在线性学习速率缩放原则基础上使用 256个GPU在1小时的时间内完成了ResNet50模型的训练，并首次将批次大小提升至 8K，而且精度不会下降。
You等人\cite{lars}采用层式自适应速率缩放 （LARS）， 通过在不同的网络层中设置不同的学习速率，在不损失精度的前提下，将 ResNet50训练的批次大小扩展到 32K。
Smith等人~\cite{don2}通过调整动量系数来适应 SGD中的随机波动，从而进一步将批次规模增加到 64K。
Tao lin ~\cite{don}提出了本地 SGD的新层级扩展，并证明它能够有效地适应异构分布系统中的多个计算成本水平。

\subsection{弹性训练}
然而，传统的同步SGD在弹性训练环境中可能面临严重的精度下降问题。
在理想情况下，云环境中的所有资源都应以自适应伸缩的方式、动态实时地按需提供给不同用户，随着任务负载的变化对资源进行弹性配置和调整。
在弹型训练中，参与计算的设备类型或数量可能会随着时间的推移而变化。
为了解决这个问题，Robbins等人提出了动态SGD算法（dSGD）~\cite{mom_sgd}。作者发现，准确性下降的原因是当批次大小发生变化时，动量差异与以前的迭代不匹配。
动态 SGD 使用动量补偿，当将小批量大小增加到 $k$倍时，逐渐改变接下来迭代的学习速率，可以平滑噪声动量估计的影响。学习率缩放比率 $\gamma$动量补偿可以表述为以下形式：

\vspace{-4mm}
%\begin{equation}
\begin{align*}
	\label{e5}
	\gamma &= \left\{
	\begin{array}{lr}
		1+\frac{t-t_0}{T}(k-1) & { \textup{if $t-t_0 < T$}}\\
		\\
		k & {\textup{otherwise}}
	\end{array} \right.
	\tag*{(4)}
\end{align*}

当批次大小增加时，$t_0$是迭代次数标号，$T$是补偿迭代的总次数，当$T = 8k$时，可以正常完成训练，
通过引入动量补偿，动态训练的准确性可以恢复到可接受的水平。
但是，补偿过程需要相对较长的时间，因此无法适应云中参与设备数量的快速变化。

此外，最新开发的Trison\cite{triton}更具备了CPU-GPU异构计算、弹性调度、负载均衡等多种功能，但是该框架目前并不支持DNN模型训练。
Elastic Horovod\cite{elhorovod}可支持设备数量可变化的动态训练，但不支持多设备异构协同计算功能。

\subsection{处理器微优化}
随着半导体技术的发展，多核CPU突破了功率限制，通过核心并行性大大提高了性能。但是，由于计算性能与内存带宽不匹配，
内存墙\cite{multicores1,memwall}问题导致CPU相比GPU或其他加速器
（如Brainwave\cite{brainwave}、Centaur\cite{centaur}、TPU\cite{tpu}）在DL应用中性能低下。
目前，深度学习领域对CPU比对GPU或其他加速器的关注要少。

对于基于 x86 的 CPU 架构，深度神经网络的数学内核库（MKL-DNN 又名 oneDNN ~\cite{mkldnn1}）
已开发了一系列针对特定操作（如卷积）的优化。MKL-DNN 通过结构特定的技术（如线程优化、缓存阻塞、矢量化和块注册）一定程度上缓解了计算性能和内存带宽之间的不匹配。
例如，Intel已将多核CPU的内存布局从"NCHW"更改为"nChw8c"~\cite{mkldnn}，这使得内侧循环中的内存访问尽可能连续，
从而提高缓存命中率。Beidi Chen等人~\cite{DBLP:slide}提出了SLIDE（Sub-LInear 深度学习引擎），
该引擎选择性地对多层感知器 （MLP）网络中的大多数神经元进行稀疏，以减少计算，某些结果甚至优于此类网络上GPU的执行速度。
DeepCPU~\cite{2018DeepCPU}通过在L3缓存中共享模型权重来改善基于CPU的RNN网络训练。
TensorDIMM ~\cite{tensordimm}、DeepRecSys \cite{deeprecsys} 和 RecNMP\cite{recnmp} 等工作
都通过类似的张量操作和缓存处理改善了基于CPU的推荐系统DNN性能。

此外，最新研究表明限制模型尺寸可以满足新兴应用的低延迟要求，
例如，量化~\cite{int8}将DNN 中的浮点算术转换为整型算术运算（例如，从fp32 转换为 int8），
理论上可以实现四倍的推理速度，使得实时推理任务在移动设备上也可以实用。
此外，还有研究人员建议用更少的比特位进行量化，以达到更高的运行速度，
例如：BWN （二元神经网络）~\cite{bwn} 使用二元权重，TWN （三元重量网络）~\cite{twn} 使用+1、0 和 +1的三种权重，XNOR-Net~\cite{xornet} 使用二进制卷积神经网络，
但是这些量化方法由于丢失了数据的比特信息，也会不可避免地会降低模型的准确性。
张量编译器（如 TVM ~\cite{tvm}、GLOW ~\cite{glow}和 Tensor-Compreendsions~\cite{tensorcom}）在不同的架构下提供端到端优化，
通过从高度抽象中总结各种DL优化的经验，并允许用户以自动化或半自动化的方式高效搜索的实现空间，从而简化开发人员的模型部署。
Tianqi Chen~\cite{tianqi}等人提出了基于$O(\sqrt{N})$内存复杂性算法的"空间交易速度"算法，
以解决存储大型 DNN 模型时的 GPU 内存不足问题，该模型丢弃了部分低成本的即时结果，并在需要时仅恢复一次。
解耦L1D~\cite{DD} 算法有选择地绕过数据使用量低的L1D 缓存，并直接将其发布到下一个内存级别，以减少L1D 缓存竞争。

\section{云安全}
在云环境中，由于不同用户数据的物理界限被消除，
不同用户共享包括内存、磁盘、网络等多种计算资源，在数据传输和共享过程中，
因非法访问导致数据泄漏、被篡改的可能性大大提高。
为了保障云用户数据以及云上应用的安全性，近年来面向云环境的可信执行环境技术被广泛研究。

\subsection{加密算法}
数据加密和完整性验证仍然是保证数据安全目前最重要技术手段。
传统的数据加密技术可分为对称加密技术和非对称加密技术。
其中，对称加密使用相同的加密和解密秘钥，如AES加密算法\cite{aes-gcm}，DES加密算法\cite{des}，
非对称加密使用公钥加密和私钥解密，如RSA算法\cite{rsa}。
对称加密的效率较高，但非对称加密的安全性更高。
然而，这些传统的加密方案在云端环境中会面临密钥分发和密钥管理等复杂问题，
而且由于云存储系统中用户数据放在开放环境下，对数据安全性和可操作性的要求更高。
云端存储的数据完整性验证\cite{wanzhengxing}是近期云存储安全技术的研究热点之一。
基本的完整性验证过程如下。用户A在把文件F存储在云端之前，首先对文件F进行哈希运算，
并把结果hash(F)保存在可信第三方。用户B需要读取云端上存储的文件F。假设读取结果为F’，
用户B将比较hash(F’)和第三方存储的hash(F)是否一致。
如果一致，则说明数据完整；反之则说明数据被损坏或篡改。

\subsection{可信执行环境}

云平台安全依赖操作系统、数据库、虚拟化等技术，而这些系统/技术会本身存在原生的安全问题，
使攻击者可利用系统/技术漏洞实现其攻击目的。
同时，平台上的第三方系统软件、应用软件等可能会在安装或升级过程中被修改或植入攻击性模块。

可信执行环境将可信程序与外界环境隔离开来，使其免受外界影响，从而达到运行安全的目的，被广泛应用于可信云环境中。
可信执行环境，是CPU上的一块区域，可用于给数据和代码的执行提供一个更安全的空间，并保证它们的机密性和完整性。
目前所有主要的CPU架构都根据自己的特点有已实现的TEE解决方案（英特尔SGX\cite{intel-sgx}、AMD SEV\cite{amd}，ARM TrustZone\cite{trustzone}
RISC-V Keystone\cite{riskv}）或正在实现的方案（英特尔TDX\cite{tdx}，ARM-CCA\cite{armcca}。TEE使用户（如：
云计算用户）以私有方式运行其敏感应用程序，并防止特权攻击者（如：云服务商）
窃听或篡改的内存区域。TEE技术的出现使得一些新的应用模式得以快速发展，如：。

但目前的TEE解决方案往往存在一些不足，要么在安全性方面不能提供涵盖包括机密性、完整性、新鲜性、匿名性在内的全局保护措施，
要么虽然能提供较完善的安全性能，但在加载或执行时消耗大量计算资源，导致应用程序效率降低。

\subsection{存储加密}

Linux内核本身提供了一套块设备存储安全模块，
并分别提供了机密性（DM-crypt）、完整性（DM-integrity、DM-verity）保护，
但这些模块与目前云安全环境中的威胁模型不匹配，使用场景局限性较大，
无法有效预防有特权的在线攻击手段，并且无法对新鲜性和匿名性提供保护。

Intel-SGX提供内置的磁盘加密文件系统PFS来保证可执行环境中用户的存储安全。
PFS的加密基于MHT\cite{mht}结构，该结构也广泛应用于区块链中\cite{blockchain}以及。
在传统的加密MHT中，叶子节点用来保存数据块的密文，并用AES-GCM\cite{aes-gcm}加密，
MHT的中间节点称为哈希节点，保存其子节点的MAC和KEY（KEY由密钥生成算法随机生成），
并将其保存的子节点加密信息作为块数据，之后也使用AES-GCM加密。
这个过程是迭代的，也就是说叶子（密文）的KEY和MAC被保存在其父节点上，
其父节点的KEY与MAC被保存在其祖父节点上，一直到根。因此，要解密任意一个数据块，都要先获得该数据块的KEY和MAC（用于验证），
而数据块的KEY和MAC被保存在其父节点上，因此必须先得到其父节点的明文信息，
类似的，父节点的加密信息被保存在祖父节点上，所以还需要先解密祖父节点，
以此类推，重复这一过程直到根节点，再进行回溯，
时间复杂度为$O(logN)$，其中$N$是数据块的个数。
数据块的加密是类似的迭代过程，时间复杂度也为$O(logN)$。

Intel-SGX PFS采用一种变种MHT结构（如图\ref{pfs}所示），PFS中的变种MHT的中间节点也保管数据，这样做的优势在每次追加写文件时，可以直接将新数据块补充在MHT的末尾，
其次，这种变种结构可以很方便的确定每个数据块的物理位置。Intel-SGX虽然有效保证机密性、完整性、新鲜性，但出于执行效率的考虑，未对其磁盘元数据进行加密，也导致了匿名性不足，有针对元数据发起侧通道攻击的可能性，而且Intel—SGX内置的磁盘文件加密系统PFS在处理随机写IO时，
表现十分缓慢，严重影响应用程序的执行效率。

\begin{figure}[t]
	\includegraphics[width=0.8\linewidth]{ppt-thesis/pfs.png}
	\centering
	\caption{Intel-SGX PFS磁盘布局，箭头表示箭头出发方向的节点的KEY与MAC由箭头指向的节点所保管。
	}
	%\vspace{-3mm}
	\label{pfs}
\end{figure}

此外，Oblivate\cite{obliviate}是一种抵抗侧通道攻击的安全文件系统，但它会带来巨大的性能开销。
SecureFS\cite{securefs}是另一种安全的文件系统，并解决了一部分IO效率的问题，但它只是在工作负载以小数据集为主时效率较高。
